﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using Data.GameData;
using Data.GameData.Utils;
using Data.GameData.GameMap;

namespace GUIDialogs
{
    public partial class StarSystemDetails : BaseDialog
    {
        #region Attributes
        private Race race;
        private StarSystemInformation starInfo = null;
        private StarSystem starSystem = null;

        // Grid Views
        private SourceGrid.Cells.Views.Cell moonLmAlignment;
        #endregion

        #region Constructors
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="sysId">Id to a StarSystemInformation in the GameStore("StarInfo")</param>
        public StarSystemDetails(Guid sysId)
        {
            InitializeComponent();
            Initialise();

            //starInfo = GameDataStore.GetStoreContents("StarInfo").Find(star => star.Id == sysId) as StarSystemInformation;
            race = Race.ActiveRace;
            starInfo = Race.ActiveRace.KnownStarSystems.FirstOrDefault(star => star.Id == sysId) as StarSystemInformation;
            if (starInfo != null)
                starSystem = StarSystem.StarSystems.Find(star => star.Id == starInfo.SystemId);
            PopulateInfo();
        }

        public StarSystemDetails(StarSystem sys, Race race)
        {
            InitializeComponent();
            Initialise();

            starSystem = sys;
            this.race = race;
            PopulateInfo();
        }

        public StarSystemDetails(StarSystemInformation sys)
        {
            InitializeComponent();
            Initialise();

            race = Race.ActiveRace;
            starSystem = StarSystem.StarSystems.Find(star => star.Id == sys.SystemId);
            PopulateInfo();
        }

        private void Initialise()
        {
            moonLmAlignment = new SourceGrid.Cells.Views.Cell();
            moonLmAlignment.TextAlignment = DevAge.Drawing.ContentAlignment.MiddleRight;

            starTypeComboBox.Items.Add("No Star");
            starTypeComboBox.Items.Add(EnumUtils.StringValueOf(StarType.BLUE_GIANT));
            starTypeComboBox.Items.Add(EnumUtils.StringValueOf(StarType.WHITE_STAR));
            starTypeComboBox.Items.Add(EnumUtils.StringValueOf(StarType.YELLOW_STAR));
            starTypeComboBox.Items.Add(EnumUtils.StringValueOf(StarType.ORANGE_STAR));
            starTypeComboBox.Items.Add(EnumUtils.StringValueOf(StarType.RED_STAR));
            starTypeComboBox.Items.Add(EnumUtils.StringValueOf(StarType.RED_DWARF));
            starTypeComboBox.Items.Add(EnumUtils.StringValueOf(StarType.WHITE_DWARF));
            starTypeComboBox.Items.Add(EnumUtils.StringValueOf(StarType.RED_GIANT));

            starTypeComboBox.SelectedItem = EnumUtils.StringValueOf(StarType.YELLOW_STAR);
        }
        #endregion

        #region Public Properties
        public string StarSystemName
        {
            get { return systemNameTextBox.Text; }
            set { systemNameTextBox.Text = value; }
        }

        public bool HideGenerateButton
        {
            get { return generateButton.Visible; }
            set { generateButton.Visible = value; }
        }
        #endregion

        #region Private Methods
        private void StarSystemDetails_Load(object sender, EventArgs e)
        {
            systemGrid.ColumnsCount = 6;
            systemGrid.FixedRows = 1;
            systemGrid.Rows.Insert(0);

            systemGrid["columnLM"] = SourceGrid.Cells.Editors.Factory.Create(typeof(int));
            systemGrid["columnLM"].EditableMode = SourceGrid.EditableMode.DoubleClick | SourceGrid.EditableMode.F2Key;
            systemGrid[0, 0] = new SourceGrid.Cells.ColumnHeader("LM");

            systemGrid["columnRadian"] = SourceGrid.Cells.Editors.Factory.Create(typeof(int));
            systemGrid["columnRadian"].EditableMode = SourceGrid.EditableMode.DoubleClick | SourceGrid.EditableMode.F2Key;
            systemGrid[0, 1] = new SourceGrid.Cells.ColumnHeader("Radian");

            systemGrid["columnType"] = SourceGrid.Cells.Editors.Factory.Create(typeof(string));
            systemGrid["columnType"].EditableMode = SourceGrid.EditableMode.DoubleClick | SourceGrid.EditableMode.F2Key;
            systemGrid[0, 2] = new SourceGrid.Cells.ColumnHeader("Type");

            systemGrid["columnREI"] = SourceGrid.Cells.Editors.Factory.Create(typeof(double));
            systemGrid["columnREI"].EditableMode = SourceGrid.EditableMode.DoubleClick | SourceGrid.EditableMode.F2Key;
            systemGrid[0, 3] = new SourceGrid.Cells.ColumnHeader("REI");

            systemGrid["columnHR"] = SourceGrid.Cells.Editors.Factory.Create(typeof(int));
            systemGrid["columnHR"].EditableMode = SourceGrid.EditableMode.DoubleClick | SourceGrid.EditableMode.F2Key;
            systemGrid[0, 4] = new SourceGrid.Cells.ColumnHeader("HR");

            systemGrid["columnPopulation"] = SourceGrid.Cells.Editors.Factory.Create(typeof(int));
            systemGrid["columnPopulation"].EditableMode = SourceGrid.EditableMode.DoubleClick | SourceGrid.EditableMode.F2Key;
            systemGrid[0, 5] = new SourceGrid.Cells.ColumnHeader("Population");

            BuildSystemTable();

            systemGrid.AutoSizeCells();
        }

        private void PopulateInfo()
        {
            if (starInfo != null)
            {
                systemNameTextBox.Text = starInfo.Name;
            }

            if (starSystem != null && starSystem.Suns.Count() != 0)
            {
                SystemBody sun = starSystem.Suns.FirstOrDefault();

                starTypeComboBox.SelectedItem = EnumUtils.StringValueOf(sun.StarType);
            }
        }

        private void BuildSystemTable()
        {
            if (starSystem != null && starSystem.Suns.Count() != 0)
            {
                SystemBody sun = starSystem.Suns.FirstOrDefault();

                // change to while when binaries are introduced and the GUI updated
                if (sun != null)
                {
                    foreach (SystemBody planet in sun.Satalites.OrderBy(p => p.RadiusLM))
                    {
                        AddRow(planet);

                        foreach (SystemBody moon in planet.Satalites.OrderBy(m => m.RadiusLM))
                            AddRow(moon);
                    }
                }
            }
        }

        private void AddRow(SystemBody body)
        {
            //SourceGrid.Cells.Controllers.Button linkClickEvent = new SourceGrid.Cells.Controllers.Button();
            //linkClickEvent.Executed += new EventHandler(PopulationLink_Click);

            int row = systemGrid.Selection.ActivePosition.Row;
            if (row == -1)
                row = systemGrid.RowsCount;
            else
                row = ++row;

            systemGrid.Rows.Insert(row);

            systemGrid[row, 0] = new SourceGrid.Cells.Cell(body.RadiusLM, systemGrid["columnLM"]);
            if (body.Type == SystemBodyType.MOON)
                systemGrid[row, 0].View = moonLmAlignment;

            systemGrid[row, 1] = new SourceGrid.Cells.Cell(body.InitialBearing, systemGrid["columnRadian"]);

            systemGrid[row, 2] = new SourceGrid.Cells.Cell(EnumUtils.StringValueOf(body.Enviroment), systemGrid["columnType"]);
            systemGrid[row, 2].Tag = body;
            
            systemGrid[row, 3] = new SourceGrid.Cells.Cell(body.REI * 100, systemGrid["columnREI"]);
            
            systemGrid[row, 4] = new SourceGrid.Cells.Cell(body.HabRating, systemGrid["columnHR"]);
            //systemGrid[row, 4].ToolTipText = EnumUtils.stringValueOf(SystemBodyCompatability.BENIGN);

            if (body.Population != null)
                systemGrid[row, 5] = new SourceGrid.Cells.Cell(body.Population.Size, systemGrid["columnPopulation"]);
            else
                systemGrid[row, 5] = new SourceGrid.Cells.Cell(0, systemGrid["columnPopulation"]);
            //if (body.Population != null)
            //{
            //    systemGrid[row, 5] = new SourceGrid.Cells.Link(body.Population.Size.ToString());
            //    systemGrid[row, 5].Controller.AddController(linkClickEvent);
            //}
            //else
            //{
            //    systemGrid[row, 5] = new SourceGrid.Cells.Link("0");
            //    systemGrid[row, 5].Controller.AddController(linkClickEvent);
            //}
        }
        #endregion

        #region GUI Callbacks
        private void gridContextMenuStrip_Opening(object sender, CancelEventArgs e)
        {
            int row = systemGrid.Selection.ActivePosition.Row;

            if (row == -1) // Only header
            {
                addPlanetToolStripMenuItem.Enabled = true;
                addMoonToolStripMenuItem.Enabled = false;
                deleteToolStripMenuItem.Enabled = false;
            }
            else
            {
                SystemBody body = systemGrid[row, 2].Tag as SystemBody;
                if (body.Type == SystemBodyType.SUN ||
                    body.Type == SystemBodyType.PLANET ||
                    body.Type == SystemBodyType.ASTEROID)
                {
                    addPlanetToolStripMenuItem.Enabled = true;
                    addMoonToolStripMenuItem.Enabled = true;
                    deleteToolStripMenuItem.Enabled = true;
                    return;
                }

                if (body.Type == SystemBodyType.MOON)
                {
                    addPlanetToolStripMenuItem.Enabled = false;
                    addMoonToolStripMenuItem.Enabled = true;
                    deleteToolStripMenuItem.Enabled = true;
                    return;
                }
            }
        }

        private void addPlanetToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SystemBody sun = GetSun();
            SystemBody planet = new SystemBody(starSystem.Id, SystemBodyType.PLANET, SystemBodyEnviroment.TYPE_T, 2, 10, sun);
            AddRow(planet);
        }

        private void addMoonToolStripMenuItem_Click(object sender, EventArgs e)
        {
            int row = systemGrid.Selection.ActivePosition.Row;
            SystemBody planet = systemGrid[row, 2].Tag as SystemBody;
            while( planet.Type != SystemBodyType.PLANET)
                planet = systemGrid[--row, 2].Tag as SystemBody;

            SystemBody moon = new SystemBody(starSystem.Id, SystemBodyType.MOON, SystemBodyEnviroment.TYPE_O2, 1, 2, planet);
            AddRow(moon);

        }

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            int row = systemGrid.Selection.ActivePosition.Row;
            if (row != -1)
            {
                SystemBody body = systemGrid[row, 2].Tag as SystemBody;
                if (body != null)
                    body.Orbits = null;

                systemGrid.Rows.Remove(row);
            }
        }

        private SystemBody GetSun()
        {
            if ("No Star" == starTypeComboBox.SelectedItem as string)
                return null;

            SystemBody sun;

            if (starSystem.Suns.Count() == 0)
            {
                sun = new SystemBody(starSystem.Id, SystemBodyType.SUN, SystemBodyEnviroment.TYPE_O3, 3, 0, null);
                sun.StarType = (StarType)EnumUtils.EnumValueOf(starTypeComboBox.SelectedItem as string, typeof(StarType));
                sun.MapPosition = new MapIndex(starSystem.MapId, 35, 35);

                starSystem.AddSun(sun);
            }
            else
            {
                sun = starSystem.Suns.FirstOrDefault();
            }

            return sun;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void generateButton_Click(object sender, EventArgs e)
        {
            if (systemGrid.Rows.Count() > 1)
                systemGrid.Rows.RemoveRange(1, systemGrid.Rows.Count() - 1);

            SystemBody sun = GetSun();
            if( sun == null )
                return;

            sun.ClearSatalites();

            StarType starType = (StarType)EnumUtils.EnumValueOf(starTypeComboBox.SelectedItem as string, typeof(StarType));
            if( starType == StarType.BLUE_GIANT || starType == StarType.WHITE_DWARF || starType == StarType.RED_GIANT )
                return;

            List<int> bodyOrbits = SystemGeneration.CalculatePlanetaryOrbits();
            foreach (int orbit in bodyOrbits)
            {
                SystemBody body = new SystemBody(starSystem.Id, SystemBodyType.PLANET, SystemBodyEnviroment.TYPE_O2, 1, orbit, sun);
                SystemGeneration.DertermineEnviroment(starType, orbit, ref body);
                AddRow(body);

                if (body.Type == SystemBodyType.PLANET)
                {
                    int moons = SystemGeneration.MoonCount(body.Mass, body.Enviroment);
                    for (int m = 0; m < moons; m++)
                    {
                        SystemBodyEnviroment moonType;
                        switch (body.Enviroment)
                        {
                            case SystemBodyEnviroment.TYPE_I:
                                moonType = SystemBodyEnviroment.TYPE_O1;
                                break;
                            case SystemBodyEnviroment.TYPE_V:
                            case SystemBodyEnviroment.TYPE_O3:
                                moonType = SystemBodyEnviroment.TYPE_O3;
                                break;
                            default:
                                moonType = SystemBodyEnviroment.TYPE_O2;
                                break;
                        }

                        SystemBody moon = new SystemBody(starSystem.Id, SystemBodyType.MOON, moonType, 0, 1, body);
                        AddRow(moon);
                    }
                }
            }

            systemGrid.AutoSizeCells();
        }

        private void PopulationLink_Click(object sender, EventArgs e)
        {
            SourceGrid.CellContext context = (SourceGrid.CellContext)sender;
            SourceGrid.Cells.Link btnCell = (SourceGrid.Cells.Link)context.Cell;
            
            // Open the details
            //btnCell.Value = DateTime.Now.TimeOfDay.ToString();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void systemGrid_MouseClick(object sender, MouseEventArgs e)
        {
            //if (e.Button == MouseButtons.Right)
            //{
            //    SourceGrid.Position pos = systemGrid.MouseCellPosition;
            //    if (pos.Row != -1)
            //    {
            //        systemGrid.Selection.ResetSelection(false);
            //        systemGrid.Selection.SelectRow(pos.Row, true);
            //        systemGrid.Focus(true);
            //    }
            //}
        }
        #endregion

        #region Overrides
        protected override bool IsValid()
        {
            bool result = true;
            //if (shortNameTextBox.Text.Length == 0)
            //{
            //    errorProvider.SetError(shortNameTextBox, "You must enter a name");
            //    result = false;
            //}
            //else
            //{
            //    errorProvider.SetError(shortNameTextBox, "");
            //}

            return result;
        }

        protected override void UpdateData()
        {
            if (starInfo != null)
            {
                starInfo.Name = systemNameTextBox.Text;
            }

            if (starSystem != null)
            {
                SystemBody sun = GetSun();

                sun.StarType = (StarType)EnumUtils.EnumValueOf(starTypeComboBox.SelectedItem as string, typeof(StarType));

                int row = 1;
                while (row < systemGrid.Rows.Count())
                {
                    SystemBody body = systemGrid[row, 2].Tag as SystemBody;
                    if (body != null)
                    {
                        body.RadiusLM = int.Parse(systemGrid[row, 0].DisplayText);
                        body.InitialBearing = int.Parse(systemGrid[row, 1].DisplayText);
                        body.Enviroment = (SystemBodyEnviroment)EnumUtils.EnumValueOf(systemGrid[row, 2].DisplayText, typeof(SystemBodyEnviroment));
                        body.REI = double.Parse(systemGrid[row, 3].DisplayText) / 100;
                        body.HabRating = int.Parse(systemGrid[row, 4].DisplayText);

                        // Moons are not added to the strategic maps (yet)
                        if (body.Type != SystemBodyType.MOON)
                            body.MapPosition = Map.MapPositionFrom(sun.MapPosition, body.InitialBearing, body.RadiusLM, true);

                        // Add the body to the store.
                        starSystem.AddBody(body);

                        // Populations
                        int popSize =  int.Parse(systemGrid[row, 5].DisplayText);
                        if (popSize != 0 || body.Population != null)
                        {
                            if (body.Population != null)
                            {
                                if (popSize == 0)
                                {
                                    race.RemovePopulation(body.Population);
                                    body.Population = null;
                                }
                                else
                                {
                                    body.Population.Size = popSize;
                                }
                            }
                            else
                            {
                                body.Population = new Population(body, race.Id, popSize);
                                race.AddPopulation(body.Population);
                            }
                        }
                    }

                    ++row;
                }
            }
        }
        #endregion
    }
}
